package com.gzy.cs5.service;

import com.gzy.cs5.Repository.OrderRepository;
import com.gzy.cs5.exception.BusinessException;
import com.gzy.cs5.exception.ErrorCode;
import com.gzy.cs5.lang.ItemType;
import com.gzy.cs5.lang.OrderStatus;
import com.gzy.cs5.model.Item;
import com.gzy.cs5.model.Order;

import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 订单服务具体实现
 */
public class SimpleOrderService extends BaseOrderService {

    private Timer timer;

    public SimpleOrderService(OrderRepository repository) {
        super(repository);
        this.timer = new Timer();
        scheduleOrderCleanup();
    }
    public SimpleOrderService() {

    }


    /**
     * 创建订单，使用当前时间为订单创建时间
     *
     * @param items     订单中的商品列表
     * @param isVIP     是否为VIP用户
     * @return 创建的订单对象
     * @throws BusinessException 如果商品验证失败或订单创建失败
     */
    @Override
    public Order createOrder(List<Item> items, boolean isVIP) throws BusinessException {
        return createOrder(items, isVIP, LocalDateTime.now());
    }

    /**
     * 创建订单，使用指定时间为订单创建时间
     *
     * @param items     订单中的商品列表
     * @param isVIP     是否为VIP用户
     * @param currentTime 订单创建时间
     * @return 创建的订单对象
     * @throws BusinessException 如果商品验证失败或订单创建失败
     */
    @Override
    public Order createOrder(List<Item> items, boolean isVIP, LocalDateTime currentTime) throws BusinessException {
        validateItems(items, currentTime);

        double totalPrice = calculateTotalPrice(items, isVIP);

        Order order = new Order(
                UUID.randomUUID().toString(),
                items,
                OrderStatus.CREATED,
                totalPrice,
                currentTime,
                isVIP
        );

        repository.save(order);
        return order;
    }

    /**
     * 取消订单
     *
     * @param orderId 订单ID
     * @param currentTime 当前时间
     * @throws BusinessException 如果订单不存在、状态无效或取消超时
     */
    @Override
    public void cancelOrder(String orderId, LocalDateTime currentTime) throws BusinessException {
        Order order = repository.findById(orderId);
        if (order == null) {
            throw new BusinessException(ErrorCode.ORDER_NOT_FOUND);
        }

        if (order.getStatus() != OrderStatus.CREATED) {
            throw new BusinessException(ErrorCode.ORDER_STATUS_INVALID);
        }

        Duration duration = Duration.between(order.getCreateTime(), currentTime);
        if (duration.toMinutes() > 30) {
            throw new BusinessException(ErrorCode.ORDER_CANCEL_TIMEOUT);
        }

        order.setStatus(OrderStatus.CANCELLED);
        repository.updateStatus(orderId, OrderStatus.CANCELLED);
    }

    /**
     * 获取所有订单
     *
     * @return 所有订单列表
     */
    @Override
    public List<Order> getAllOrders() {
        return repository.findAll();
    }

    /**
     * 根据订单ID获取订单
     *
     * @param orderId 订单ID
     * @return 订单对象，如果不存在则返回null
     */
    @Override
    public Order getOrderById(String orderId) throws BusinessException {
        if (orderId == null){
            throw new BusinessException(ErrorCode.ORDER_NOT_FOUND);
        }
        return repository.findById(orderId);
    }

    /**
     * 更新订单状态
     *
     * @param orderId 订单ID
     * @param status  新的状态
     * @throws BusinessException 如果订单不存在或状态转换无效
     */
    @Override
    public void updateOrderStatus(String orderId, OrderStatus status) throws BusinessException {
        Order order = repository.findById(orderId);
        if (order == null) {
            throw new BusinessException(ErrorCode.ORDER_NOT_FOUND);
        }

        // 检查状态转换是否合法
        switch (status) {
            case CREATED:
                throw new BusinessException(ErrorCode.ORDER_STATUS_INVALID_TRANSITION);
            case PROCESSING:
                if (order.getStatus() != OrderStatus.CREATED) {
                    throw new BusinessException(ErrorCode.ORDER_STATUS_INVALID_TRANSITION);
                }
                break;
            case PENDING:
                if (order.getStatus() != OrderStatus.PROCESSING) {
                    throw new BusinessException(ErrorCode.ORDER_STATUS_INVALID_TRANSITION);
                }
                break;
            case PAID:
                if (order.getStatus() != OrderStatus.PENDING) {
                    throw new BusinessException(ErrorCode.ORDER_STATUS_INVALID_TRANSITION);
                }
                break;
            case COMPLETED:
                if (order.getStatus() != OrderStatus.PAID) {
                    throw new BusinessException(ErrorCode.ORDER_STATUS_INVALID_TRANSITION);
                }
                break;
            case CANCELLED:
                if (order.getStatus() != OrderStatus.CREATED && order.getStatus() != OrderStatus.PROCESSING) {
                    throw new BusinessException(ErrorCode.ORDER_STATUS_INVALID_TRANSITION);
                }
                break;
            default:
                throw new BusinessException(ErrorCode.ORDER_STATUS_INVALID);
        }

        order.setStatus(status);
        repository.updateStatus(orderId, status);
    }

    /**
     * 验证订单中的商品
     *
     * @param items 订单中的商品列表
     * @param currentTime 当前时间
     * @throws BusinessException 如果商品验证失败
     */

    public void validateItems(List<Item> items, LocalDateTime currentTime) throws BusinessException {
        if (items == null || items.isEmpty()) {
            throw new BusinessException(ErrorCode.ORDER_EMPTY);
        }

        boolean hasMain = items.stream().anyMatch(item -> item.getType() == ItemType.MAIN);
        if (!hasMain) {
            throw new BusinessException(ErrorCode.ORDER_NO_MAIN_ITEM);
        }

        boolean hasDessert = items.stream().anyMatch(item -> item.getType() == ItemType.DESSERT);
        if (hasDessert && !hasMain) {
            throw new BusinessException(ErrorCode.ORDER_DESSERT_WITHOUT_MAIN);
        }

        boolean hasIceCoffee = items.stream().anyMatch(item -> item.getName().equalsIgnoreCase("冰咖啡"));
        if (hasIceCoffee && currentTime.getHour() >= 15) {
            throw new BusinessException(ErrorCode.ORDER_ICE_COFFEE_AFTER_3PM);
        }

        // 库存校验
        checkStock(items);
    }

    /**
     * 检查商品库存
     *
     * @param items 订单中的商品列表
     * @throws BusinessException 如果商品不存在或库存不足
     */
    private void checkStock(List<Item> items) throws BusinessException {
        for (Item item : items) {
            Item existingItem = repository.findItemById(item.getItemId());
            if (existingItem == null) {
                throw new BusinessException(ErrorCode.ITEM_NOT_FOUND, item.getName());
            }
            if (existingItem.getStock() < 1) {
                throw new BusinessException(ErrorCode.ITEM_OUT_OF_STOCK, item.getName());
            }
            existingItem.setStock(existingItem.getStock() - 1);
            repository.updateItem(existingItem);
        }
    }



    /**
     * 计算订单总价
     *
     * @param items 订单中的商品列表
     * @param isVIP 是否为VIP用户
     * @return 订单总价
     */
    public double calculateTotalPrice(List<Item> items, boolean isVIP) throws BusinessException {
        double totalPrice = 0.0;
        Map<String, Integer> drinkCountMap = new HashMap<>();
        boolean dessertDiscountApplied = false; // 标记是否已经应用了甜品优惠

        // 检查商品数量是否超过5个
        if (items.size() > 5) {
            throw new BusinessException(ErrorCode.ORDER_ITEM_LIMIT_EXCEEDED);
        }

        // 套餐优惠：汉堡 + 薯条 = 25元（原价30元）
        boolean hasBurger = items.stream().anyMatch(item -> item.getName().equalsIgnoreCase("汉堡"));
        boolean hasFries = items.stream().anyMatch(item -> item.getName().equalsIgnoreCase("薯条"));

        if (hasBurger && hasFries) {
            totalPrice += 25.0;
            // 移除汉堡和薯条
            items = items.stream()
                    .filter(item -> !item.getName().equalsIgnoreCase("汉堡") && !item.getName().equalsIgnoreCase("薯条"))
                    .collect(Collectors.toList());
        } else {
            // 原价计算汉堡和薯条
            for (Item item : items) {
                if (item.getName().equalsIgnoreCase("汉堡") || item.getName().equalsIgnoreCase("薯条")) {
                    totalPrice += item.getPrice();
                }
            }
            // 移除已经计算过的汉堡和薯条
            items = items.stream()
                    .filter(item -> !item.getName().equalsIgnoreCase("汉堡") && !item.getName().equalsIgnoreCase("薯条"))
                    .collect(Collectors.toList());
        }

        // 统计每种饮料的数量
        for (Item item : items) {
            if (item.getType() == ItemType.DRINK) {
                drinkCountMap.put(item.getName(), drinkCountMap.getOrDefault(item.getName(), 0) + 1);
            }
        }

        // 第二杯半价：同种饮料第二杯半价
        for (Map.Entry<String, Integer> entry : drinkCountMap.entrySet()) {
            int count = entry.getValue();
            double drinkPrice = items.stream()
                    .filter(item -> item.getName().equalsIgnoreCase(entry.getKey())) // 根据名称过滤饮料
                    .findFirst() // 获取第一个匹配的饮料
                    .map(Item::getPrice) // 获取饮料价格
                    .orElse(0.0); // 如果未找到，价格设为0.0
            if (count > 1) { // 只有数量大于1时才应用第二杯半价
                int fullPriceCount = count / 2;
                int halfPriceCount = count - fullPriceCount;
                totalPrice += fullPriceCount * drinkPrice + halfPriceCount * drinkPrice * 0.5;
            } else {
                totalPrice += drinkPrice; // 数量为1时按原价计算
            }
        }

        // 买一送一：甜品买一送一（每个用户最多生效一次）
        for (Item item : items) {
            if (item.getType() == ItemType.DESSERT) {
                if (!dessertDiscountApplied) {
                    totalPrice += item.getPrice(); // 只收取一个的价格
                    dessertDiscountApplied = true; // 标记已应用优惠
                }
            }
        }

        // 满减优惠：总价大于100元且非周末时，满减10元
        if (totalPrice > 100 && !isWeekend(LocalDateTime.now())) {
            totalPrice -= 10.0;
        }

        // VIP折扣：VIP用户享受9折优惠
        if (isVIP) {
            totalPrice *= 0.9;
        }

        return totalPrice;
    }

    /**
     * 安排订单清理任务
     */
    private void scheduleOrderCleanup() {
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    List<Order> orders = repository.findAll();
                    LocalDateTime currentTime = LocalDateTime.now();
                    for (Order order : orders) {
                        if (order.getStatus() == OrderStatus.CREATED) {
                            Duration duration = Duration.between(order.getCreateTime(), currentTime);
                            if (duration.toMinutes() > 30) {
                                order.setStatus(OrderStatus.CANCELLED);
                                try {
                                    repository.updateStatus(order.getOrderId(), OrderStatus.CANCELLED);
                                    System.out.println("自动取消订单: " + order.getOrderId());
                                } catch (BusinessException e) {
                                    System.err.println("更新订单状态失败: " + order.getOrderId() + ", 错误信息: " + e.getMessage());
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    System.err.println("订单清理任务执行失败: " + e.getMessage());
                }
            }
        }, 0, 60000); // 每分钟检查一次
    }

    /**
     * 判断日期是否为周末
     *
     * @param date 日期
     * @return 如果是周末返回true，否则返回false
     */
    private boolean isWeekend(LocalDateTime date) {
        DayOfWeek dayOfWeek = date.getDayOfWeek();
        return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;
    }
}
